﻿/*
 *	Copyright (c) 2009 Queensland University of Technology. All rights reserved.
 *	The QUT Bioinformatics Collection is open source software released under the 
 *	Microsoft Public License (Ms-PL): http://www.microsoft.com/opensource/licenses.mspx.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using QUT.Bio.SilverMap.ObjectModel;

namespace BlastExplorer.SilverMapDataProducer {
	/// <summary>
	/// A SequenceKey combines source and id strings to provide s lightly
	/// less error prone scheme than that provided by simple string ids.
	/// </summary>
	
	public class SequenceKey: IComparable<SequenceKey>, IEquatable<SequenceKey> {
		#region Property: Source.
		/// <summary>
		/// Get the source.
		/// </summary>

		public SequenceSource Source {
			get;
			private set;
		} 
		#endregion 
		
		#region Property: Id
		/// <summary>
		/// Get the Id.
		/// </summary>

		public string Id {
			get;
			private set;
		} 
		#endregion

		#region Constructor ( SequenceSource source, string id )
		/// <summary>
		/// Initialise a new SequenceKey, setting the source and id.
		/// </summary>
		/// <param name="source">The source of the sequence.</param>
		/// <param name="id">The id of the sequence relative to the source.</param>

		public SequenceKey (
			SequenceSource source,
			string id
		) {
			Source = source;
			Id = id;
		} 
		#endregion

		#region Constructor ( XElement element )
		/// <summary>
		/// Initialises a SequenceKey from and xml element.
		/// </summary>
		/// <param name="element">An element containing at a minimum a pair of attributes: Source and Id.</param>

		public SequenceKey ( XElement element ) 
		: this ( 
			(SequenceSource) Enum.Parse( typeof(SequenceSource), element.Attribute("Source").Value ),
			element.Attribute( "Id" ).Value
		) {
		}
		#endregion

		#region Static readonly variable: Empty.
		/// <summary>
		/// Gets an empty SequenceKey, useful as a "null" value.
		/// </summary>

		public static readonly SequenceKey Empty = new SequenceKey( SequenceSource.Unknown, "" ); 
		#endregion

		#region Method: ToString
		/// <summary>
		/// Gets a text representation of thie sequqnce key.
		/// </summary>
		/// <returns></returns>

		public override string ToString () {
			return String.Format( "{0}|{1}", Source, Id );
		} 
		#endregion

		#region Method: CompareTo( SequenceKey )
		/// <summary>
		/// Compares this sequence key to another, ordering by Source, Id.
		/// </summary>
		/// <param name="other">A sequence key against which the sequqnce key is to be ranked.</param>
		/// <returns>Less than 0, 0, or greater than 0, according to the rank of the sequence relative to the other.</returns>

		public int CompareTo ( SequenceKey other ) {
			int result = Source.CompareTo( other.Source );

			if ( result == 0 ) {
				result = Id.CompareTo( other.Id );
			}

			return result;
		} 
		#endregion

		#region Method: Equals( SequenceKey other )
		/// <summary>
		/// Determines if the sequqnce key is identical to another.
		/// </summary>
		/// <param name="other">The other key.</param>
		/// <returns>CompareTo(other) == 0.</returns>

		public bool Equals ( SequenceKey other ) {
			return CompareTo( other ) == 0;
		} 
		#endregion

		#region Method: Equals ( object obj )
		/// <summary>
		/// Determines if the sequqnce key is identical to another.
		/// </summary>
		/// <param name="obj">The other key.</param>
		/// <returns>CompareTo(obj) == 0.</returns>

		public override bool Equals ( object obj ) {
			return Equals( (SequenceKey) obj );
		} 
		#endregion

		#region Method: GetHashCode ()
		/// <summary>
		/// Gets a hash code that is consistent with Equals.
		/// </summary>
		/// <returns>A hash code that is consistent with Equals.</returns>

		public override int GetHashCode () {
			return Source.GetHashCode() << 5 + Id.GetHashCode();
		} 
		#endregion
		
		#region Method: ToXml ()
		/// <summary>
		/// Serialises the sequence key to an xml element.
		/// </summary>
		/// <returns></returns>
		
		public XElement ToXml () {
			return new XElement( "SequenceKey",
				new XAttribute( "Source", Source ),
				new XAttribute( "Id", Id )
			);
		}
		#endregion
	}
}
